liburing_cpp: Add wrapper API for PrepReadFixed() Bug: 400674947 Test: liburing_cpp_tests Change-Id: I678f18601472dcd0c76e4a5084020fe8e83927cf Signed-off-by: Akilesh Kailash <akailash@google.com> 
diff --git a/liburing_cpp/Android.bp b/liburing_cpp/Android.bp index e17f080..8566bc2 100644 --- a/liburing_cpp/Android.bp +++ b/liburing_cpp/Android.bp 
@@ -1,4 +1,3 @@ -  package {  // See: http://go/android-license-faq  // A large-scale-change added 'default_applicable_licenses' to import @@ -9,31 +8,32 @@  }    cc_library { -	name: "liburing_cpp", -	host_supported: true, -	recovery_available: true, -	srcs: [ -	"src/IoUring.cpp", -	"src/IoUringSQE.cpp", -	], -	static_libs: [ -	"liburing", -	], -	export_include_dirs: [ -	"include", -	], + name: "liburing_cpp", + host_supported: true, + recovery_available: true, + ramdisk_available: true, + vendor_ramdisk_available: true, + srcs: [ + "src/IoUring.cpp", + "src/IoUringSQE.cpp", + ], + static_libs: [ + "liburing", + ], + export_include_dirs: [ + "include", + ],  }   -  cc_test_host { -	name: "liburing_cpp_tests", -	srcs: [ -	"tests/BasicTests.cpp", -	"tests/main.cpp", -	], -	static_libs: [ -	"libgtest", -	"liburing", -	"liburing_cpp", -	], + name: "liburing_cpp_tests", + srcs: [ + "tests/BasicTests.cpp", + "tests/main.cpp", + ], + static_libs: [ + "libgtest", + "liburing", + "liburing_cpp", + ],  } 
diff --git a/liburing_cpp/include/liburing_cpp/IoUring.h b/liburing_cpp/include/liburing_cpp/IoUring.h index 09ed5cc..b382630 100644 --- a/liburing_cpp/include/liburing_cpp/IoUring.h +++ b/liburing_cpp/include/liburing_cpp/IoUring.h 
@@ -53,6 +53,12 @@  // Register a set of file descriptors to kernel.  virtual Errno RegisterFiles(const int* files, size_t files_size) = 0;  virtual Errno UnregisterFiles() = 0; + + // Prepare read to a registered buffer. This does not submit the operation + // to the kernel. For that, call |IoUringInterface::Submit()| + virtual IoUringSQE PrepReadFixed( + int fd, void* buf, unsigned nbytes, uint64_t offset, int buf_index) = 0; +  // Append a submission entry into this io_uring. This does not submit the  // operation to the kernel. For that, call |IoUringInterface::Submit()|  virtual IoUringSQE PrepRead(int fd, void *buf, unsigned nbytes, 
diff --git a/liburing_cpp/src/IoUring.cpp b/liburing_cpp/src/IoUring.cpp index cf10272..8589220 100644 --- a/liburing_cpp/src/IoUring.cpp +++ b/liburing_cpp/src/IoUring.cpp 
@@ -82,6 +82,19 @@  return ret;  }   + IoUringSQE PrepReadFixed(int fd, + void* buf, + unsigned nbytes, + uint64_t offset, + int buf_index) override { + auto sqe = io_uring_get_sqe(&ring); + if (sqe == nullptr) { + return IoUringSQE{nullptr}; + } + io_uring_prep_read_fixed(sqe, fd, buf, nbytes, offset, buf_index); + return IoUringSQE{static_cast<void*>(sqe)}; + } +  IoUringSQE PrepRead(int fd, void* buf, unsigned nbytes,  uint64_t offset) override {  auto sqe = io_uring_get_sqe(&ring); 
diff --git a/liburing_cpp/tests/BasicTests.cpp b/liburing_cpp/tests/BasicTests.cpp index 81288f6..680fb64 100644 --- a/liburing_cpp/tests/BasicTests.cpp +++ b/liburing_cpp/tests/BasicTests.cpp 
@@ -191,4 +191,51 @@  for (int i = 0; i < data.size(); ++i) {  ASSERT_EQ(data[i], i % 256);  } -} \ No newline at end of file +} + +TEST_F(IoUringTest, ExtentReadFixedBuffers) { + const int fd = fileno(fp); + ASSERT_NO_FATAL_FAILURE(WriteTestData(fd, kBlockSize * 3, kBlockSize)); + ASSERT_NO_FATAL_FAILURE(WriteTestData(fd, kBlockSize * 5, kBlockSize)); + ASSERT_NO_FATAL_FAILURE(WriteTestData(fd, kBlockSize * 8, kBlockSize)); + ASSERT_NO_FATAL_FAILURE(WriteTestData(fd, kBlockSize * 13, kBlockSize)); + fsync(fd); + + std::vector<unsigned char> data; + data.resize(kBlockSize * 4); + std::unique_ptr<struct iovec[]> vecs = std::make_unique<struct iovec[]>(4); + for (int i = 0; i < 4; i++) { + vecs[i].iov_base = data.data() + i * kBlockSize; + vecs[i].iov_len = kBlockSize; + } + + ASSERT_TRUE(ring->RegisterBuffers(vecs.get(), 4).IsOk()); + + ASSERT_TRUE( + ring->PrepReadFixed(fd, data.data(), kBlockSize, 3 * kBlockSize, 0) + .IsOk()); + ASSERT_TRUE( + ring->PrepReadFixed( + fd, data.data() + kBlockSize, kBlockSize, 5 * kBlockSize, 1) + .IsOk()); + ASSERT_TRUE( + ring->PrepReadFixed( + fd, data.data() + kBlockSize * 2, kBlockSize, 8 * kBlockSize, 2) + .IsOk()); + ASSERT_TRUE( + ring->PrepReadFixed( + fd, data.data() + kBlockSize * 3, kBlockSize, 13 * kBlockSize, 3) + .IsOk()); + ring->SubmitAndWait(4); + const auto cqes = ring->PopCQE(4); + if (cqes.IsErr()) { + FAIL() << cqes.GetError().ErrMsg(); + return; + } + for (const auto& cqe : cqes.GetResult()) { + ASSERT_GT(cqe.res, 0); + } + for (int i = 0; i < data.size(); ++i) { + ASSERT_EQ(data[i], i % 256); + } +}